package com.jingxuan.service.impl;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.jingxuan.common.constant.RedisKeyConstants;
import com.jingxuan.mapper.ProductsMapper;
import com.jingxuan.service.ProductsTypeService;

import lombok.extern.slf4j.Slf4j;


@Slf4j
@Service
public class ProductsTypeServiceImpl implements ProductsTypeService {
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    @Autowired
    private ProductsMapper productsMapper;

    /**
     * 记录所有商品类型到Redis
     * 使用Set数据结构存储，自动去重
     * 设置7天过期时间，定期刷新
     */
    @Override
    public void recordAllProductsType() {
        try {
            // 从数据库查询所有不重复的商品类型
            List<String> productTypes = productsMapper.selectAllProductTypes();
            
            if (productTypes == null || productTypes.isEmpty()) {
                log.warn("没有商品类型");
                return;
            }
            
            // 删除旧的缓存
            String redisKey = RedisKeyConstants.PRODUCTS_TYPE_PREFIX;
            stringRedisTemplate.delete(redisKey);
            
            // 将所有类型添加到Redis Set中
            String[] typesArray = productTypes.toArray(new String[0]);
            stringRedisTemplate.opsForSet().add(redisKey, typesArray);
            
            // 设置过期时间为7天
            stringRedisTemplate.expire(redisKey, 7, TimeUnit.DAYS);
            
            log.info("成功记录 {} 个商品类型到Redis, key={}", 
                    productTypes.size(), redisKey);
            log.debug("商品类型: {}", productTypes);
            
        } catch (Exception e) {
            log.error("记录商品类型到Redis失败", e);
            throw new RuntimeException("记录商品类型到缓存失败", e);
        }
    }
    
    /**
     * 从Redis获取所有商品类型
     * 如果Redis中不存在，则从数据库重新加载
     */
    @Override
    public Set<String> getAllProductTypes() {
        try {
            String redisKey = RedisKeyConstants.PRODUCTS_TYPE_PREFIX;
            Set<String> types = stringRedisTemplate.opsForSet().members(redisKey);
            
            // 如果Redis中没有数据，则重新加载
            if (types == null || types.isEmpty()) {
                log.info("商品类型未找到在Redis中, 从数据库重新加载");
                recordAllProductsType();
                types = stringRedisTemplate.opsForSet().members(redisKey);
            }
            
            return types != null ? types : Collections.emptySet();
        } catch (Exception e) {
            log.error("获取商品类型从Redis失败", e);
            return Collections.emptySet();
        }
    }
    
    /**
     * 检查商品类型是否存在于Redis中
     */
    @Override
    public boolean isProductTypeExists(String type) {
        if (type == null || type.trim().isEmpty()) {
            return false;
        }
        
        try {
            String redisKey = RedisKeyConstants.PRODUCTS_TYPE_PREFIX;
            Boolean exists = stringRedisTemplate.opsForSet().isMember(redisKey, type);
            
            // 如果Redis中没有这个key，先加载数据再判断
            if (exists == null || !exists) {
                Set<String> allTypes = getAllProductTypes();
                exists = allTypes.contains(type);
            }
            
            return exists != null && exists;
        } catch (Exception e) {
            log.error("检查商品类型是否存在在Redis中失败, type={}", type, e);
            return false;
        }
    }
    
    /**
     * 获取Redis中商品类型的数量
     */
    @Override
    public Long getProductTypeCount() {
        try {
            String redisKey = RedisKeyConstants.PRODUCTS_TYPE_PREFIX;
            Long count = stringRedisTemplate.opsForSet().size(redisKey);
            
            // 如果Redis中没有数据，则重新加载
            if (count == null || count == 0) {
                recordAllProductsType();
                count = stringRedisTemplate.opsForSet().size(redisKey);
            }
            
            return count != null ? count : 0L;
        } catch (Exception e) {
            log.error("获取商品类型数量从Redis失败", e);
            return 0L;
        }
    }
}
